﻿#include <iostream>
#include <locale>
#include <string>

struct Magic
{
    Magic(const std::string &cast_name)
      : full_name("Player casts ")
    {
         full_name += cast_name;
    }

    std::string full_name;
};

namespace std
{
    ostream & operator<<(ostream & s, const Magic &m)
    {
        s << m.full_name;
        return s;
    }
}

Magic operator "" _cast(const char *cast_name, unsigned int num_chars)
{
    return Magic(std::string(cast_name, num_chars));
}


constexpr double operator "" _mm(long double v)
{
    return v / 1000.f;
}

constexpr double operator "" _mm(unsigned long long v)
{
    return operator "" _mm((long double)v);
}

constexpr double operator "" _sm(long double v)
{
    return v / 100.f;
}

constexpr double operator "" _sm(unsigned long long v)
{
    return operator "" _sm((long double)v);
}

constexpr double operator "" _dm(long double v)
{
    return v / 10.f;
}

constexpr double operator "" _dm(unsigned long long v)
{
    return operator "" _dm((long double)v);
}

constexpr double operator "" _m(long double v)
{
    return v;
}

constexpr double operator "" _m(unsigned long long v)
{
    return operator "" _m((long double)v);
}


std::string operator "" _joke(const char *text, unsigned int num_char)
{
    std::string ret(text, num_char);

    for (auto &ch : ret)
    {
        static unsigned int joker = 0;
        if ((++joker) & 1u)
        {
            ch = std::toupper(ch);
        }
    }

    return ret;
}

constexpr unsigned long long reverser()
{
    return 0;
}

template <typename ...Params>
constexpr unsigned long long reverser(char first, Params ...args)
{
    return (unsigned long long)(first - '0') + reverser(args...) * 10u;
}

template <char ...Params>
constexpr unsigned long long operator "" _reversed()
{
    return reverser(Params...);
}

using namespace std;

int main()
{
    char raw[] = R"(\h\a\h\a\n\n\n\n)";
    cout << raw << endl;

    char utf8[] = u8"Hello == Привет";
//  Not implemented yat in gnu stdc++ library
//    locale loc(std::locale::classic(), new codecvt_utf8<wchar_t>());
//
//    cout.imbue(loc);
    cout << utf8 << endl;

    char16_t utf16[] = u"Hello == Привет";
    //cout.imbue(std::locale("en_US.UTF-16"));
    cout << utf16 << endl;

    char32_t utf32[] = U"Hello == Привет";
    //cout.imbue(std::locale("en_US.UTF-32"));
    cout << utf32 << endl;


    cout << "BOOM"_cast << endl;


    cout << "Distance in SI: " << 5005.7_mm << endl;
    cout << "Distance in SI: " << 31_sm << endl;
    cout << "Distance in SI: " << 71_dm << endl;
    cout << "Distance in SI: " << 30_m << endl;

    cout << "hello world"_joke << endl;

    cout << "Reversed 1234: " << 1234_reversed << endl;

    cin.get();

    return 0;
}
